package org.lemon.cla.dto.response;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; // 需要引入 Jackson 库
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Optional;

@RestControllerAdvice // 作用于所有 @Controller 和 @RestController
public class GlobalResponseWrapper implements ResponseBodyAdvice<Object> {
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 判断当前 ResponseBodyAdvice 是否适用于给定的返回类型和 HttpMessageConverter。
     * 只有返回 true 时，beforeBodyWrite 方法才会被调用。
     *
     * @param returnType    控制器方法的返回类型
     * @param converterType 即将使用的 HttpMessageConverter 类型
     * @return 如果应该应用此 advice，则为 true；否则为 false。
     */
    @Override
    public boolean supports(MethodParameter returnType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        // 如果返回类型已经是 ResponseResult 类型，则不再进行封装，避免重复封装。
        if (returnType.getParameterType().equals(ResponseResult.class)) {
            return false;
        }

        // 排除 Swagger/OpenAPI 的相关端点，避免对文档生成造成影响。
        String className = returnType.getContainingClass().getName();
        if (className.contains("springdoc") || className.contains("swagger")) {
            return false;
        }
        return true;
    }

    /**
     * 在 HttpMessageConverter 将响应体写入到客户端之前，对响应体进行修改。
     *
     * @param body              即将写入到客户端的响应体对象
     * @param returnType        控制器方法的返回类型
     * @param selectedContentType 协商后的响应内容类型
     * @param converterType     即将使用的 HttpMessageConverter 类型
     * @param request           当前的 ServerHttpRequest 对象
     * @param response          当前的 ServerHttpResponse 对象
     * @return 修改后的响应体对象，该对象将被写入到客户端
     */
    @Override
    public Object beforeBodyWrite(Object body,
                                  MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> converterType,
                                  ServerHttpRequest request,
                                  ServerHttpResponse response) {

        // 如果原始返回值为 null，也将其封装为成功响应
        if (body == null) {
            return ResponseResult.success(Optional.ofNullable(null));
        }

        // 特殊处理 String 类型。

        if (body instanceof String) {
            try {
                // 将 ResponseResult<String> 对象转换为 JSON 字符串
                return objectMapper.writeValueAsString(ResponseResult.success(body));
            } catch (JsonProcessingException e) {
                // 转换失败时，打印日志并返回一个内部错误信息
                System.err.println("Error processing String response with ObjectMapper: " + e.getMessage());
                return ResponseResult.fail(500, "Internal Server Error during String serialization.");
            }
        }

        // 对于其他非 String 类型的成功响应，直接将其封装到 ResponseResult 对象中
        return ResponseResult.success(body);
    }
}
